package com.zh.chat.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import javax.swing.JOptionPane;

import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;

import org.apache.commons.lang.StringUtils;

import com.zh.chat.entity.Friend;
import com.zh.chat.entity.UDPProtocol;
import com.zh.chat.entity.User;
import com.zh.chat.entity.UserInfo;
import com.zh.chat.gui.ChatFrame;
import com.zh.chat.monitor.FileChangeAdapter;
import com.zh.chat.monitor.FileMonitor;
import com.zh.chat.net.FileClient;
import com.zh.chat.net.voice.ChatReceive;
import com.zh.chat.net.voice.ChatSend;
import com.zh.chat.util.FileOperationUtil;
import com.zh.chat.util.FileType;

class AnalyzeThread implements Runnable {
	private com.zh.chat.entity.UDPProtocol protocol = null;
	ClientContext clientContext = null;

	public AnalyzeThread(UDPProtocol protocol, ClientContext context) {
		this.protocol = protocol;
		this.clientContext = context;
	}

	public void run() {
		try {
			analyzeSwitcher();
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.getMessage(), "出现异常",
					JOptionPane.ERROR_MESSAGE);
		}// 分析客户端发送过来的请求
	}

	/**
	 * 根据传入的参数字符串做出不同的反应
	 * 
	 * @param command
	 * @throws Exception
	 */
	private void analyzeSwitcher() throws Exception {

		/**
		 * protocol的格式请参看命令表
		 */

		if (protocol != null) {// 确定用户是在线用户的情况下执行switch
			switch (protocol.getCode()) {
			case UDPProtocol.REQ_KEEP_ONLINE:
				keepOnline();
				break;// 保持在线
			case UDPProtocol.RESP_SEND_MSG:
				getMsgFromUser();
				break;// 发送消息给某用户
			case UDPProtocol.RESP_USERINFO:
				reciveUseInfo();
				break;// 接收用户资料
			case UDPProtocol.RESP_FRIENDS_LIST:
				reciveFriends();
				break;// 获取好友
			case UDPProtocol.RESP_FRIEND_MATERIAL:
				reciveFriend();
				break;// 获取某个好友资料
			case UDPProtocol.RESP_MODIFY_PASSWORD:
				modifyPwd();
				break;// 修改某ID密码
			case UDPProtocol.RESP_MODIFY_MATERIAL:
				modifyUser();
				break;// 修改某ID的用户资料
			case UDPProtocol.RESP_MODIFY_PROFILE:
				modifyHead();
				break;// 修改头像图片
			case UDPProtocol.RESP_MODIFY_FRIEND_DIVIDED:
				modifyFriDivide();
				break;// 修改某个好友的分组
			case UDPProtocol.RESP_ADD_FRIEND:
				addFriend();
				break;// 增加好友到某个分组
			case UDPProtocol.RESP_DEL_FRIEND:
				delFriend();
				break;// 删除好友
			case UDPProtocol.RESP_SERVER_SEND_FILE_ACK:
				reciveFile();
				break;// 接收文件
			case UDPProtocol.RESP_RECIVE_VOICE:
				startVoice();
				break;// 接收文件
			case UDPProtocol.RESP_LOGIN:
				respLogin();
				break;// 登入
			case UDPProtocol.RESP_LOGOUT:
				logout();
				break;// 登出
			case UDPProtocol.RESP_IP:
				getIP();
				break;// 接收发送回来的IP地址
			case UDPProtocol.RESP_CHANGE_STATUS:
				changeStatus();
				break;// 改变用户状态
			case UDPProtocol.RESP_REGIST:
				register();
				break;// 注册
			default:
				break;//
			}
		}
	}

	/**
	 * 处理服务器发送过来的保持在线UDP指令
	 */
	private void keepOnline() {
		// controller.keepOnline();
		// if (user.getStatus() == UserStatus.CHECKING) {
		// User client = (User)protocol.getData();
		// user.setStatus(client.getStatus());
		// OnlineUserManager.setStatus(user.getSysId(), client.getStatus());
		// } else {
		// System.out.println("用户"+user.getSysId()+"已经掉线");
		// }
	}

	/**
	 * 接收用户用户资料，紧接着请求好友列表
	 */
	private void reciveUseInfo() {
		UserInfo userInfo = new UserInfo();
		Object object = protocol.getData();
		if (object instanceof User)
			userInfo.initUser((User) object);
		clientContext.setUserInfo(userInfo);

		/**
		 * 请求好友列表
		 */
		UDPProtocol protocol = new UDPProtocol();
		protocol.setCode(UDPProtocol.REQ_FRIENDS_LIST);
		protocol.setRequestId(userInfo.getSysId());
		protocol.setTargetId(0L);
		clientContext.getNetService().send(protocol);// 发送请求
	}

	/**
	 * 接收的其他用户发送过来的消息
	 * 
	 * @param targetId
	 * @param requestId
	 * @param text
	 */
	private void getMsgFromUser() {
		java.lang.Long reqId = protocol.getRequestId();
		java.lang.Long tarId = protocol.getTargetId();
		Object object = protocol.getData();
		if (reqId == -1) {
			JOptionPane.showMessageDialog(null, (String) object);
			return;
		}
		if (reqId != 0) {
			ChatFrame chatFrame = clientContext.getChatFrame(reqId);
			if (chatFrame != null) {// 已经存在聊天窗口
				if (object instanceof String) {
					chatFrame.setVisible(true);
					chatFrame.appendChatLog(protocol);// 接收消息
					clientContext.writeChatLog(chatFrame.getFriend(), protocol);
				}
			} else {// 不存在聊天窗口，需要新建
				Friend friend = clientContext.getUserInfo().getFriend(reqId);
				if (friend != null) {
					ChatFrame frame = new ChatFrame(friend);
					frame.setClientContext(clientContext);
					frame.setVisible(true);
					// 添加到MAP中以便之后聊天时取用
					clientContext.addChatFrame(reqId, frame);
					if (object instanceof String) {
						frame.initChatLog();
						frame.appendChatLog(protocol);// 接收消息
						clientContext.writeChatLog(friend, protocol);
					}
				}
			}
		} else if (reqId == 0) {
			ChatFrame chatFrame = clientContext.getChatFrame(tarId);
			if (object instanceof String) {
				chatFrame.appendChatLog(protocol);// 接收消息
				clientContext.writeChatLog(chatFrame.getFriend(), protocol);
			}
		} else {
		}
	}

	/**
	 * 接收UDP命令根据命令中包含的TCP端口信息启动TCP线程接收好友列表文件 并根据好友列表中的好友头像名称请求服务器TCP连接
	 * 
	 * @param id
	 */
	private void reciveFriends() {
		final UserInfo userInfo = clientContext.getUserInfo();
		String path = FileOperationUtil.getFilePath(FileType.DATA,
				userInfo.getSysId(), null);
		File file = new File(path);
		if (!file.exists()) {// 如果目录不存在，新建目录
			file.mkdirs();
		}
		// 建立TCP连接，获取好友列表friendList.data文件
		clientContext.getNetService().reciveFile(path, protocol);

		FileMonitor monitor = FileMonitor.getInstance();
		// 添加文件事件监听如果文件被创建就执行请求头像操作
		monitor.addFileChangeListener(new FileChangeAdapter() {
			@Override
			public void fileExist(String filename) {
				JSONArray jarr = null;
				try {
					jarr = FileOperationUtil.getFileJSONArray(filename);
				} catch (FileNotFoundException e) {
					UDPProtocol protocol = new UDPProtocol();
					protocol.setCode(UDPProtocol.REQ_FRIENDS_LIST);
					protocol.setRequestId(userInfo.getSysId());
					protocol.setTargetId(0L);
					clientContext.getNetService().send(protocol);// 发送请求
				}

				requestFile(FileType.SCULPTURE, userInfo.getImage(),
						userInfo.getSysId());// 请求自己的头像文件
				if (jarr != null) {
					List<?> list = JSONArray.toList(jarr, new Friend(),
							new JsonConfig());
					// 请求文件
					for (Object object : list) {
						Friend f = (Friend) object;
						userInfo.addFriend(f);
						requestFile(FileType.SCULPTURE, f.getImage(),
								userInfo.getSysId());// 请求好友头像文件
					}
					clientContext.setUserInfo(userInfo);
					clientContext.getMainFrame().initUserView(userInfo);// 更新用户资料
					clientContext.getMainFrame().initFriendsTree(userInfo);// 更新好友Tree
				}
			}

			@Override
			public void fileChanged(String filename) {
				JSONArray jarr = null;
				try {
					jarr = FileOperationUtil.getFileJSONArray(filename);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}

				if (jarr != null) {
					List<?> list = JSONArray.toList(jarr, new Friend(),
							new JsonConfig());
					// 请求文件
					for (Object object : list) {
						try {
							Thread.sleep(200);
						} catch (InterruptedException e) {
						}
						Friend f = (Friend) object;
						userInfo.addFriend(f);
						requestFile(FileType.SCULPTURE, f.getImage(),
								userInfo.getSysId());// 请求好友头像文件
					}
					clientContext.setUserInfo(userInfo);
					clientContext.getMainFrame().updateFriendsTree(userInfo);// 更新好友Tree
				}
			}
		}, path + "friendList.data", 2000);

	}

	private void requestFile(int fileType, String fileName, java.lang.Long id) {
		String info = new String(fileType + ":" + fileName);
		UDPProtocol protocol = new UDPProtocol();
		protocol.setCode(UDPProtocol.REQ_SEND_FILE);
		protocol.setData(info);
		protocol.setClazz(info.getClass().getName());
		protocol.setRequestId(id);
		protocol.setTargetId(0L);
		clientContext.getNetService().send(protocol);
	}

	/**
	 * 接收服务器发送过来一位好友详细信息
	 * 
	 * @param targetId
	 * @param requestId
	 */
	private void reciveFriend() {
	}

	/**
	 * 接收用户密码修改结果
	 * 
	 * @param id
	 * @param oldpwd
	 * @param newpwd
	 */
	private void modifyPwd() {
	}

	/**
	 * 接收用户资料修改结果
	 * 
	 * @param id
	 * @param userInfo
	 */
	private void modifyUser() {
		String clazz = protocol.getClazz();
		User user = null;
		if (clazz.equals(new Boolean(false).getClass().getName())) {
			JOptionPane.showMessageDialog(null, "未修改成功");
		} else {
			user = clientContext.getUserInfo().getUser();
			clientContext.getMainFrame().updateUserView(user);
			if (clientContext.getUserInfoFrame() != null) {
				JOptionPane.showMessageDialog(null, "资料修改成功!");
				clientContext.getUserInfoFrame().setNew(true);
			}
		}
	}

	/**
	 * 更新用户头像
	 */
	private void modifyHead() {
		System.out.println("修改成功");
	}

	/**
	 * 修改某个好友的分组
	 * 
	 * @param targetId
	 * @param requestId
	 * @param divide_name
	 */
	private void modifyFriDivide() {
	}

	/**
	 * 添加好友到默认分组
	 * 
	 * @param id
	 * @param friend_id
	 * @param divide_name
	 */
	private void addFriend() {
	}

	/**
	 * 删除好友
	 * 
	 * @param targetId
	 * @param requestId
	 */
	private void delFriend() {
	}

	private void reciveFile() {
		Object o = protocol.getData();
		if (o instanceof String) {
			String info = (String) o;
			String[] infos = StringUtils.split(info, ':');
			int port = Integer.parseInt(infos[0]);
			int fileType = Integer.parseInt(infos[1]);
			String path = FileOperationUtil.getFilePath(fileType,
					protocol.getTargetId(), null);
			try {
				new FileClient(path, protocol.getServerIp(), port);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 接到服务器回复信息，根据信息作出是否开始语音连接的动作
	 * 
	 * @throws Exception
	 */
	private void startVoice() throws Exception {
		Object object = protocol.getData();
		if (object instanceof String) {
			String info = (String) object;
			String[] infos = StringUtils.split(info, ':');
			if (infos.length == 2) {// 接收到别人的请求时长度为三
				// TODO 1对方接收UDP语音的端口，2对方的IP地址
				int remotePort = Integer.parseInt(infos[0]);
				InetAddress address = null;
				ChatSend chatSend = null;
				try {
					address = InetAddress.getByName(infos[1]);
					chatSend = new ChatSend(address, remotePort);
					chatSend.start();
				} catch (UnknownHostException e) {
					throw new RuntimeException("开启语音连接时对方IP地址异常");
				} catch (IllegalArgumentException e) {
					throw new RuntimeException("开启语音连接时找不到音频输入设备");
				} catch (Exception e) {
					e.printStackTrace();
				}
				try {
					java.lang.Long reqId = protocol.getRequestId();
					ChatFrame frame = clientContext.getChatFrame(reqId);
					if (frame == null) {
						Friend friend = clientContext.getUserInfo().getFriend(
								reqId);
						frame = new ChatFrame(friend);
						clientContext.addChatFrame(reqId, frame);
						frame.setVisible(true);
					}
					frame.setVOICE_IN_REMOTE_PORT(remotePort);
					frame.setVOICE_REMOTE_IP(address);
					frame.setSendThread(chatSend);
					if (frame.getReceiveThread() == null) {
						clientContext.readyVoice(protocol.getTargetId(), protocol.getRequestId());
					}
					JOptionPane.showMessageDialog(frame,
							"您已经和" + protocol.getRequestId() + "建立语音连接");
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else if (infos.length == 1) {// 如果长度不为三而是1,说明是自己发出的请求被服务器受理了
				if (infos[0].equals("false")) {// 对方不在线或者其他原因导致没有建立连接
					JOptionPane.showMessageDialog(null, "好友不在线或其他原因导致没有连接成功");
				} else if (infos[0].equals("ok")) {
					java.lang.Long reqId = protocol.getRequestId();
					ChatFrame frame = clientContext.getChatFrame(reqId);
					ChatReceive receiveTh = new ChatReceive(
							frame.getVOICE_IN_LOCAL_PORT());
					receiveTh.start();
					frame.setReceiveThread(receiveTh);
					JOptionPane.showMessageDialog(frame, "您已经和" + reqId + "建立语音连接");
				}
			}
		}
	}

	/**
	 * 用户登录方法
	 * 
	 * @param id
	 * @param pwd
	 */
	private void respLogin() {
		Object object = protocol.getData();
		boolean ok = false;
		if (object instanceof Boolean) {
			ok = (Boolean) object;
		}
		if (ok) {
			// 清理原来的用户文件friendList.data，以及头像文件
			String path = FileOperationUtil.getFilePath(FileType.DATA,
					protocol.getTargetId(), "friendList.data");
			String path2 = FileOperationUtil.getFilePath(FileType.SCULPTURE,
					protocol.getTargetId(), null);
			File file = new File(path);
			File file2 = new File(path2);
			if (file.exists()) {
				file.delete();
			}
			if (file2.exists()) {
				file2.delete();
			}

			clientContext.getMainFrame().setVisible(true);// 显示主界面
			clientContext.getLoginFrame().setVisible(false);// 隐藏登陆界面
			protocol.setCode(UDPProtocol.REQ_USERINFO);
			protocol = clientContext.getNetService().reverse(protocol);
			clientContext.getNetService().send(protocol);// 发送请求用户资料
		} else {
			clientContext.getMainFrame().setVisible(false);
			clientContext.getLoginFrame().setVisible(true);
			clientContext.getLoginFrame().showError("用户名密码错误");
		}
	}

	/**
	 * 接收登出结果
	 * 
	 * @param id
	 */
	private void logout() {
		clientContext.stop();// 停止主程序
	}

	private void getIP() {
		String ip = protocol.getClientIp();
		Object o = protocol.getData();
		if (o instanceof String) {
			clientContext.getNetService().setIP(ip);
		}
	}

	/**
	 * 接收状态改变结果
	 */
	private void changeStatus() {
		Object object = protocol.getData();
		UserInfo userInfo = new UserInfo();
		if (object instanceof User) {
			User user = (User) object;
			userInfo.initUser(user);
			clientContext.getMainFrame().setStatus(userInfo.getStatus());
		}
	}

	/**
	 * 接收新用户注册结果
	 */
	private void register() {
		Object o = protocol.getData();
		if(o instanceof User){
			User user = (User)o;
			Long uid = user.getSysId();
			JOptionPane.showMessageDialog(null, "恭喜您已经注册成功，SIM号:"+uid);
			clientContext.getRegistFrame().dispose();
		}
	}
}// 解析命令的Thread 进程类